package com.pangu.ui.browser;

import com.pangu.AMApplication;
import com.pangu.ui.R;
import com.pangu.service.ActionException;
import com.pangu.task.AServiceWrapper;
import com.pangu.task.IResultReceiver;
import com.pangu.task.mark.ATaskMark;
import com.pangu.ui.view.CommonInfoView;
import com.pangu.util.UIConstants;

import android.content.Context;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**
 * 项加载的父类,提供加载提示。下拉和超时自刷新功能，外部使用时不同taskMark对应不同的LoadableView以避免视图状态的干扰。
 * <p/>
 * Created by cxlin
 */
public abstract class LoadableView<A extends AMApplication> extends CommonInfoView<A> implements IResultReceiver {

    public static final String TAG = LoadableView.class.getSimpleName();

    // 对应的TaskMark
    protected ATaskMark mTaskMark;
    // 内容视图
    protected View contentView;
    // 正在加载视图
    protected View loadingView;
    // 顶部视图
    protected View topView;
    // 底部视图
    protected View bottomView;
    // 已经加载完了的时候如果没有数据的时候的空视图
    private View emptyView;
    // 状态提示
    private StatusView statusView;
    // 自动加载
    private boolean mAutoLoad = true;
    // 最后一次提示状态，避免重复设置。
    private ViewStatus lastNoteState = ViewStatus.OVER;
    // 延时时间
    private final int DELAY_FLUSH_TIME = 50;

    private boolean shouldCancelStatus = false;

    private String customErrorText = null;

    public LoadableView(Context context) {
        super(context);
    }

    public LoadableView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void initLoadableView() {
        initLoadableView(null, true, true, false);
    }

    public void initLoadableView(ATaskMark taskWraper) {
        initLoadableView(taskWraper, true, true, false);
    }

    public void initLoadableView(ATaskMark taskWraper, boolean loadInit) {
        initLoadableView(taskWraper, true, loadInit, false);
    }

    /**
     * 加载列表
     *
     * @param taskMark
     * @param autoLoad  自动加载
     * @param loadInit  初始加载
     * @param forceLoad 强制加载 ,导致tryQueryNewItems一定会被执行
     */
    public void initLoadableView(ATaskMark taskMark, boolean autoLoad, boolean loadInit, boolean forceLoad) {
        // 不同的任务时重建列表。
        if (contentView == null || (taskMark == null || mTaskMark != taskMark)) {
            mTaskMark = taskMark;
            // 先初始化视图
            initView(getContext());

        } else {
            mTaskMark = taskMark;
        }

        mAutoLoad = autoLoad;
        lastNoteState = ViewStatus.OVER;

        // 在没有数据的情况下，如果条件合适自动加载数据。
        if (loadInit && mTaskMark != null && (forceLoad || isLoadDataEmpty() || mTaskMark.getTaskStatus() == ATaskMark
                .HANDLE_WAIT)) {
            tryQueryNewItems(ATaskMark.TYPE_DEFAULT);

        } else {
            if (mTaskMark != null) {
                AServiceWrapper.forceTakeoverTask(this, mTaskMark);
            }
            updateViewStatus(mTaskMark);

        }

        notifyDataSetChanged();
    }

    /**
     * 初始化
     *
     * @param context
     */
    protected void initView(Context context) {
        // 清除所有
        removeAllViews();
        loadingView = null;

        // 顶部视图
        topView = createTopView(context);
        if (topView != null) {
            addView(topView, new LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT));
        }

        // 内容视图
        contentView = createContentView();
        contentView.setOverScrollMode(OVER_SCROLL_NEVER);
        // 如果view已经设置了id则由上层自己控制id，为了解决同一个视图有两个不同类型的view有相同的id
        if (contentView.getId() == View.NO_ID) {
            contentView.setId(R.id.mui__loadable_contentview_id);
        }

        LayoutParams linerLayoutParams = new LayoutParams(LayoutParams
                .MATCH_PARENT, 0);
        linerLayoutParams.weight = 1;
        addView(contentView, linerLayoutParams);

        // 列表为空时的空视图
        emptyView = createEmptyView();
        if (emptyView != null) {
            addView(emptyView, linerLayoutParams);
        }

        // 状态提示视图
        statusView = createStatusView(context);
        if (statusView != null) {
            addView(statusView, new LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT));
        }

        // 底部视图
        bottomView = createBottomView(context);
        if (bottomView != null) {
            addView(bottomView, new LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT));
        }

        // 如果用户有自定义空视图，则先添加此视图到布局中
        updateEmptyView();

    }

    /**
     * 顶部视图
     *
     * @param context
     * @return
     */
    protected View createTopView(Context context) {
        return null;
    }

    /**
     * 创建内容视图
     *
     * @return
     */
    protected abstract View createContentView();

    /**
     * 创建默认的列表为空时的空视图，子类如果有特定需求可覆盖此方法，如果子类返回null，则表明不需要空视图
     *
     * @return
     */
    protected View createEmptyView() {
        View emptyView = LayoutInflater.from(getContext()).inflate(R.layout.mui__empty_view, null);

        return emptyView;
    }

    /**
     * 底部状态视图
     *
     * @param context
     * @return
     */
    protected StatusView createStatusView(Context context) {
        StatusView statusView = new StatusView(context);
        statusView.setBackgroundColor(getResources().getColor(R.color.mui__status_frame_bg));
        statusView.setFocusable(false);
        statusView.hideNoteView();

        return statusView;
    }

    /**
     * 底部视图
     *
     * @param context
     * @return
     */
    protected View createBottomView(Context context) {
        return null;
    }

    /**
     * 状态视图
     */
    protected class StatusView extends FrameLayout implements OnClickListener {

        protected View loadView;
        protected Button waitButton;

        public StatusView(Context context) {
            super(context);
            initNoteView(context);
        }

        public StatusView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            initNoteView(context);
        }

        private void initNoteView(Context context) {
            setFocusable(false);

            loadView = createStatusFrameLoadingView();
            loadView.setId(R.id.mui_status_frame_loading_view_id);
            loadView.setFocusable(false);
            loadView.setVisibility(View.INVISIBLE);

            waitButton = createStatusFrameWaitButton();
            waitButton.setId(R.id.mui_status_frame_wait_button_id);
            waitButton.setFocusable(false);
            waitButton.setVisibility(View.INVISIBLE);
            waitButton.setOnClickListener(this);

            addNoteFrameView(context, loadView, waitButton);

            // 初始不可见
            hideNoteView();
        }

        /**
         * 添加提示组件
         *
         * @param loadView
         * @param waitView
         */
        protected void addNoteFrameView(Context context, View loadView, TextView waitView) {
            addView(loadView);
            addView(waitView);
        }

        public void showLoadView() {
            setVisibility(VISIBLE);
            waitButton.setVisibility(GONE);
            loadView.setVisibility(VISIBLE);
        }

        public void hideWaitView() {
            waitButton.setVisibility(GONE);
        }

        public void showErrorView() {
            setVisibility(VISIBLE);
            waitButton.setVisibility(VISIBLE);
            waitButton.setText(R.string.mui__status_frame_retry);
            loadView.setVisibility(GONE);
        }

        public void showWaitView() {
            setVisibility(VISIBLE);
            waitButton.setVisibility(VISIBLE);
            waitButton.setText(R.string.mui__status_frame_load_wait);
            loadView.setVisibility(GONE);
        }

        public void hideNoteView() {
            setVisibility(GONE);
        }

        @Override
        public void onClick(View v) {
            if (v.getId() == R.id.mui_status_frame_wait_button_id && isCanManualLoad()) {
                hideNoteView();
                handleManualLoadItem();
            }
        }

        public void setCustomErrorText(String customErrorText) {
            setVisibility(VISIBLE);
            waitButton.setEnabled(false);
            waitButton.setVisibility(VISIBLE);
            waitButton.setText(customErrorText);
            loadView.setVisibility(GONE);
        }
    }

    /**
     * 是否可以手动加载任务
     *
     * @return
     */
    protected boolean isCanManualLoad() {
        if (mTaskMark == null) {
            return false;

        } else {
            return (mTaskMark.getTaskStatus() == ATaskMark.HANDLE_ERROR || mTaskMark.getTaskStatus() == ATaskMark
                    .HANDLE_WAIT);
        }
    }

    /**
     * 手动加载任务
     */
    protected void handleManualLoadItem() {
        if (mTaskMark != null) {
            if (mTaskMark.getTaskType() == ATaskMark.TYPE_DEFAULT) {
                mTaskMark.setTaskStatus(ATaskMark.HANDLE_WAIT);
                tryQueryNewItems(ATaskMark.TYPE_DEFAULT);

            } else if (mTaskMark.getTaskType() == ATaskMark.TYPE_REFRESH) {
                handleRefreshLoadItem();

            }
        }
    }

    /**
     * 加载任务并且将任务标记为刷新状态
     *
     * @return 如果正常进入任务的刷新加载，则返回true, 否则返回false
     */
    public boolean handleRefreshLoadItem() {
        if (mTaskMark != null && mTaskMark.getTaskStatus() != ATaskMark.HANDLE_DOING) {
            mTaskMark.reinitTaskMark();
            tryQueryNewItems(ATaskMark.TYPE_REFRESH);
            return true;
        }

        return false;
    }

    /**
     * 创建状态提示的进度条对象
     *
     * @return
     */
    protected View createStatusFrameLoadingView() {
        View loadingView = LayoutInflater.from(getContext()).inflate(R.layout.mui__status_frame_loading_view, null);

        return loadingView;
    }

    /**
     * 等待视图
     */
    protected Button createStatusFrameWaitButton() {
        Button waitButton = new Button(getContext());
        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT);
        waitButton.setLayoutParams(layoutParams);
        waitButton.setMinHeight(getResources().getDimensionPixelSize(R.dimen.mui__status_frame_wait_button_min_height));
        waitButton.setTextColor(getResources().getColor(R.color.mui__status_frame_wait_button_text_color));
        waitButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen
                .mui__status_frame_wait_button_font_size));
        waitButton.setGravity(Gravity.CENTER);
        waitButton.setBackgroundColor(getResources().getColor(R.color.mui__status_frame_wait_button_background_color));

        return waitButton;
    }

    /**
     * 更新视图状态，这个方法只能接受相同任务的标示。
     *
     * @param aTaskMark
     */
    protected void updateViewStatus(ATaskMark aTaskMark) {
        if (aTaskMark == null || aTaskMark == mTaskMark || aTaskMark.isSubTaskMarkOf(mTaskMark)) {
            changeViewStatus(aTaskMark);

        } else {
            throw new IllegalArgumentException("aTaskMark 不被接受：" + aTaskMark);
        }
    }

    /**
     * 视图状态的枚举
     */
    protected enum ViewStatus {
        OVER, DOING, WAIT, ERROR
    }

    /**
     * 任务的状态只能有实际的任务需求决定，视图状态由实际的操作需求决定。<br>
     * 务必确保二者是独立！<br>
     *
     * @param aTaskMark 标示当前修改状态关联的一个任务
     */
    private void changeViewStatus(ATaskMark aTaskMark) {
        if (aTaskMark == null) {
            lastNoteState = ViewStatus.OVER;

        } else {
            // 刷新任务只处理成功情况
            switch (aTaskMark.getTaskStatus()) {
                case ATaskMark.HANDLE_OVER:
                    lastNoteState = ViewStatus.OVER;
                    break;

                case ATaskMark.HANDLE_DOING:
                    lastNoteState = ViewStatus.DOING;
                    break;

                case ATaskMark.HANDLE_WAIT:
                    lastNoteState = ViewStatus.WAIT;
                    break;

                case ATaskMark.HANDLE_ERROR:
                    lastNoteState = ViewStatus.ERROR;
                    break;

                default:
                    throw new IllegalArgumentException("unknow status taskMark: " + aTaskMark);
            }
        }

        sendEmptyMessage(R.id.mui__mm_update_load_state_id);
    }

    @Override
    public void handleChainMessage(Message message) {
        if (message.what == R.id.mui__mm_update_load_state_id) {
            doUpdateStatusView();

        } else if (message.what == R.id.mui__delay_flush_view) {
            notifyDataSetChanged();

        }
    }

    /**
     * 更新视图状态
     */
    private void doUpdateStatusView() {
        if (shouldCancelStatus) {
            statusView.setVisibility(GONE);
            if (emptyView != null) {
                emptyView.setVisibility(VISIBLE);
            } else {
                LayoutParams linerLayoutParams = new LayoutParams(LayoutParams
                        .MATCH_PARENT, 0);
                linerLayoutParams.weight = 1;
                addView(contentView, linerLayoutParams);

                // 列表为空时的空视图
                emptyView = createEmptyView();
                if (emptyView != null) {
                    addView(emptyView, linerLayoutParams);
                }
            }
            return;
        }

        if (statusView == null) {
            // 无状态条也需要更新视图
            updateEmptyView();
            return;
        }

        switch (lastNoteState) {
            case DOING:
                // 没有项的时候显示大加载视图
                if (!isLoadDataEmpty() && loadingView == null && mTaskMark.getTaskType() != ATaskMark
                        .TYPE_REFRESH) {
                    statusView.showLoadView();

                } else {
                    updateEmptyView(); // 可能要显示大的加载图标
                    statusView.hideWaitView();
                }
                break;

            case ERROR:
                if (customErrorText != null) {
                    statusView.setCustomErrorText(customErrorText);
                } else {
                    statusView.showErrorView();
                }
                break;

            case WAIT:
                statusView.showWaitView();
                break;

            case OVER:
                updateEmptyView();
                statusView.hideNoteView();
                break;

            default:
                throw new IllegalArgumentException("unknow status lastNoteState: " + lastNoteState);
        }
    }

    /**
     * 更新空视图状态
     */
    protected void updateEmptyView() {
        if (mTaskMark != null && isLoadDataEmpty()) {
            if (mTaskMark.isLoadEnd()) {
                // 移除正在加载视图
                if (loadingView != null) {
                    removeView(loadingView);
                    loadingView = null;
                }

                // 自定义加载完后的空视图
                if (emptyView != null) {
                    // 没添加过则添加
                    if (indexOfChild(emptyView) == -1) {
                        LayoutParams linerLayoutParams = new LayoutParams(
                                LayoutParams.MATCH_PARENT, 0);
                        linerLayoutParams.weight = 1;
                        // 添加在列表视图的位置
                        int index = indexOfChild(contentView);
                        addView(emptyView, index, linerLayoutParams);
                    }
                    contentView.setVisibility(GONE);
                    emptyView.setVisibility(VISIBLE);

                } else {
                    clearLoadingProgressView();
                }
            } else {
                showLoadingProgeessView();
            }

        } else {
            clearLoadingProgressView();
        }
    }

    @Override
    public void flushView(int what) {
        // 通知数据视图更新
        notifyDataSetChanged();

        // 当父视图列表要刷新时，内嵌的子视图列表也要刷新
        if (topView instanceof CommonInfoView) {
            ((CommonInfoView) topView).flushView(UIConstants.NONE_VIEW);
        }
        if (bottomView instanceof CommonInfoView) {
            ((CommonInfoView) bottomView).flushView(UIConstants.NONE_VIEW);
        }

    }

    @Override
    public void receiveResult(ATaskMark taskMark, ActionException exception, Object trackerResult) {
        if (taskMark == mTaskMark || taskMark.isSubTaskMarkOf(mTaskMark)) {
            // 通知数据改变
            notifyDataSetChanged();
            // 更改视图
            updateViewStatus(taskMark);
        }
    }

    /**
     * 清除正在加载视图
     */
    public void clearLoadingProgressView() {
        if (loadingView != null) {
            removeView(loadingView);
            loadingView = null;
        }

        if (emptyView != null) {
            removeView(emptyView);
        }

        if (contentView != null && contentView.getVisibility() != VISIBLE) {
            contentView.setVisibility(VISIBLE);
        }
    }

    /**
     * 显示正在加载视图
     */
    private void showLoadingProgeessView() {
        if (loadingView == null) {
            loadingView = createLoadingView(getContext());
            LayoutParams linerLayoutParams = new LayoutParams(LayoutParams
                    .MATCH_PARENT, 0);
            linerLayoutParams.weight = 1;
            // 添加在列表视图的位置
            int index = indexOfChild(contentView);
            addView(loadingView, index, linerLayoutParams);
        }

        contentView.setVisibility(GONE);
        if (emptyView != null) {
            emptyView.setVisibility(GONE);
        }

        loadingView.setVisibility(VISIBLE);
    }

    /**
     * 正在载入视图
     *
     * @param context
     * @return
     */
    protected View createLoadingView(Context context) {
        RelativeLayout view = (RelativeLayout) LayoutInflater.from(getContext()).inflate(R.layout.mui__loading_view, null);

        return view;
    }

    /**
     * 尝试获得新的项
     */
    protected abstract void tryQueryNewItems(int taskType);

    /**
     * 判断视图数据是否为空
     *
     * @return
     */
    public abstract boolean isLoadDataEmpty();

    /**
     * 子类建议调用这个方法通知数据改变
     */
    public void notifyDataSetChanged() {
        updateEmptyView();
    }

    /**
     * 子类建议调用这个方法通知数据改变，在特定的如图片等资源时允许进行延时刷新。
     */
    public void notifyDataSetChangedDelay() {
        sendEmptyMessageDelay(R.id.mui__delay_flush_view, DELAY_FLUSH_TIME);
    }

    public ATaskMark getTaskMark() {
        return mTaskMark;
    }

    public void showTopView() {
        if (topView != null) {
            topView.setVisibility(VISIBLE);
        }
    }

    public void hideTopView() {
        if (topView != null) {
            topView.setVisibility(GONE);
        }
    }

    public void showBottomView() {
        if (bottomView != null) {
            bottomView.setVisibility(VISIBLE);
        }
    }

    public void hideBottomView() {
        if (bottomView != null) {
            bottomView.setVisibility(GONE);
        }
    }

    public boolean isAutoLoad() {
        return mAutoLoad;
    }

    public void setAutoLoad(boolean autoLoad) {
        this.mAutoLoad = autoLoad;
    }

    public void cancelStatusView() {
        shouldCancelStatus = true;
    }

    public void setCustomErrorStatusText(String errorText) {
        this.customErrorText = errorText;
    }
}
